#ifndef VENUS_SHADOW_VOLUME_SHADOW_VOLUME_DEMO_H
#define VENUS_SHADOW_VOLUME_SHADOW_VOLUME_DEMO_H

#include "ui/glut_window.h"
#include "graphics/camera.h"
#include "graphics/fps_counter.h"
#include "nvModel/nvModel.h"

namespace venus {
class ShadowVolumeDemo : public GlutWindow {
public:
  ShadowVolumeDemo(); 
  ~ShadowVolumeDemo();
  bool Initialize();
  void OnIdle();
  void OnDisplay();
  void OnResize(int width, int height);
  void OnKeyboard(unsigned char key, int x, int y);
  void OnSpecialKey(int key, int x, int y);
  void OnMouse(int button, int state, int x, int y);
  void OnMouseMove(int x, int y);
private:
  void RenderSkyBox();
  void RenderScene(bool shadow_pass);
  void UpdateLight(int i);
  void AmbientPass();
  void ShadowPass();
  void IlluminationPass();
  void FinalPass();
  bool LoadShaders();
  bool LoadTextures();
  void VisualizeStencil();
private:
  OrbitPerspectiveCameraGL camera_;
  FpsCounter fps_counter_;
  ProgramGLSL *lit_scene_program_;
  ProgramGLSL *ambient_scene_program_;
  GLint tex_var_;
  GLint light_diffuse_var_;
  ProgramGLSL *shadow_vol_program_;
  GLint extrude_bias_var_;
  GLint extrude_extent_var_;
  GLint light_pos_var_;
  GLint proj_mat_var_;
  GLint mv_mat_var_;
  ImageTextureGL *sky_box_[6];
  ImageTextureGL *model_tex_;
  ImageTextureGL *plane_tex;
  nv::Model *model_;
  nv::Model *plane_;
  nv::Model *model2_;
  static const int light_count_ = 1;
  FlyMotion *lights_[light_count_];
  float proj_mat_[16];
  float mv_mat_[16];
  OrbitMotion light_;
  bool left_button_down_;
  bool right_button_down_;
  Point last_mouse_pos_;
  bool show_shadow_volume_;
};
} // namespace venus

#endif // VENUS_SHADOW_VOLUME_SHADOW_VOLUME_DEMO_H
